PackerでAMIをぱかっと作ってみた

PackerでAMIをぱかっと作ってみた

Clock Icon2019.05.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今回はPackerを使ってAMIを作ってみました。ですのでその記録をブログに書いておきます。

Packerとは

HashiCorp社が出している、AWS、GCP、Azure、Docker、VirtualBoxといった様々な環境で使用できるマシンイメージを自動で作ることができるツールです。
今回はAWS上で検証したのでAMIを作成できました。

実際にAMIを作成する手順は下記のような流れになりました。

  1. 事前準備
  2. テンプレートの作成
  3. AMIの作成

事前準備

Packerのインストール

macOSだと下記コマンドでインストールできます。

$ brew install packer

またソースコードも公開されているのでコードを元にコンパイルすることもできます。

IAM Userの準備

CLIアクセスできるIAM Userの作成とAccess KeySecret Access Keyをお手元に準備してください。

テンプレートの作成

Packerではマシンイメージの作成をテンプレートと呼ばれるファイルを元に作成します。
json形式のファイルで今回定義したのはざっくりとこんな内容です。

Key Value Description
type amazon-ebs 作成するマシンイメージのデプロイ先
region ap-northeast-1 AMIを作成するリージョン
source_ami ami-0f9ae750e8274075b 作成するAMIのベースになるAMI(今回はAmazonLinux2)
ssh_username ec2-user インスタンス起動時にSSH接続するためのユーザ
ami_name packer101-ami amiにつける名前
provisioners 省略 AMIイメージ作成時に実行するコマンド

そしてテンプレートファイルの中身はこんな感じです。

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "ap-northeast-1",
      "source_ami": "ami-0f9ae750e8274075b",
      "instance_type": "t2.micro",
      "ssh_username": "ec2-user",
      "ami_name": "packer101-ami"
    }
  ],
    "provisioners": [
      {
        "type":  "shell",
        "inline": [
          "sudo yum -y update",
          "sudo yum -y install httpd",
          "sudo systemctl start httpd && sudo systemctl enable httpd"
        ]
      }
    ]
}

それでは実際に AMIを作成する...前にテンプレートの構文があっているかを確認しましょう。

$ packer validate packer101.json

Template validated successfully.

こんな感じの出力が出たら構文に問題はありません。エラーが出たら修正して、実際にAMIをビルドしましょう!

AMI の作成

下記のコマンドでAMIが作成されます。 AWS_* のところには先ほど作成したIAM Userの情報を入れましょう。

$ export AWS_ACCESS_KEY_ID="XXXXXXXXXXXXXXX"
$ export AWS_SECRET_ACCESS_KEY="YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
$ packer build packer101.json

buildを実行すると、EC2インスタンスが起動され、起動されたEC2インスタンスを元にAMIが作成されます。 実際にビルドの途中でEC2インスタンスを確認してみると...。

$ aws ec2 describe-instances  --query Reservations[].Instances[].Tags[].Value

Packer Builder

Packer Builder というEC2インスタンスが立ち上がっていますね。 そしてこれを元にAMIが作成されていきます。

ビルドの出力が下記のように出たらAMIが使用可能になっています。

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
ap-northeast-1: ami-xxxxxxxxxxxx

これを元にインスタンスを立ち上げればhttpd が起動してあるインスタンスが出来上がります。
実際にアクセスしてみると、テストページが無事表示されました!

Switch Role してAMIの作成をする

Switch RoleしないとAWS CLIを使えないから、上の方法は使えないという場合も安心してください。

先ほどのテンプレートに profile を追加して、そこにスイッチ先のRoleを書けばいいだけなのです。
ついでにMFAの対応も書いておきます。こちらもちょろっと追記すれば問題ありません。

先ほどのテンプレートファイルに下記のような変更を加えれば大丈夫です。

{
  "variables": {
    "mfa_code": "000000"
  },
  "builders": [
    {
      ~~~
      "profile": "switch",
      "mfa_code": "{{user `mfa_code`}}",
      ~~~
    }
  ]
}

このように変更することでMFA対応と、 switch という名前のロールにスイッチして実行してくれます。
そしたらAMIを作成しましょう。変数のmfa_codeに6桁の数字を渡せばOKです。

$ packer build -var "mfa_code=123456" packer101.json

テンプレートをちょっと便利にする

今のテンプレートでも十分に便利ですけどそれよりちょっと便利にして新しいAMIを作りましょう。
なのでまずは、既存のAMIを削除します。

$ aws ec2 deregister-image --image-id ami-xxxxxxxxxxxx

消したらテンプレートファイルを書き換えます。
具体的にはベースとなるAMIをいつでも最新のAmazon Linux 2にします。

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "ap-northeast-1",
      "instance_type": "t2.micro",
      "ssh_username": "ec2-user",
      "ami_name": "packer101-ami",
      "source_ami_filter": {
        "filters": {
          "name": "amzn2-ami-hvm-*-x86_64-gp2"
        },
        "owners": ["137112412989"],
        "most_recent": true
      }
    }
  ],
    "provisioners": [
      {
        "type":  "shell",
        "inline": [
          "sudo yum -y update",
          "sudo yum -y install httpd",
          "sudo systemctl start httpd && sudo systemctl enable httpd"
        ]
      }
    ]
}

先ほどまで ami_name で直接AMI IDを指定していたのをフィルターでうまいこと最新のものを取得するように変更します。
それではもう一度AMIを作成します。

$ packer validate packer101.json
$ packer build packer101.json

buildで出力された AMI IDを元に生成がされているかを確認しましょう。

$ aws ec2 describe-images --image-id ami-xxxxxxxxxxx --query Images[].Name
packer101-ami

問題なくAMIが作成されましたね。

最後に

今回はPackerの素振りということであまり複雑なことはやりませんでした。
ですが、変数やAnsibleなどなど様々な機能がPackerでは使用できます。
AMIのイメージをコードで管理できるのは非常に良さげです。

参考資料

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.